package io.effi.rpc.support;

import io.effi.rpc.common.constant.Constant;
import io.effi.rpc.common.event.EventDispatcher;
import io.effi.rpc.common.executor.RpcThreadPool;
import io.effi.rpc.common.extension.spi.Extension;
import io.effi.rpc.contract.ThreadPool;
import io.effi.rpc.contract.module.ApplicationConfiguration;
import io.effi.rpc.contract.module.EffRpcApplication;
import io.effi.rpc.contract.module.EffiRpcModule;
import io.effi.rpc.contract.module.ModuleConfiguration;
import io.effi.rpc.metrics.event.CalleeMetricsEvent;
import io.effi.rpc.metrics.event.CalleeMetricsEventListener;
import io.effi.rpc.metrics.event.CallerMetricsEvent;
import io.effi.rpc.metrics.event.CallerMetricsEventListener;
import io.effi.rpc.metrics.filter.CalleeExecuteRecordFilter;
import io.effi.rpc.metrics.filter.CallerMetricsFilter;
import io.effi.rpc.transport.event.IdleEvent;
import io.effi.rpc.transport.event.IdleEventListener;
import io.effi.rpc.transport.event.RefreshHeartBeatCountEvent;
import io.effi.rpc.transport.event.RefreshHeartBeatCountEventListener;

import java.util.concurrent.ExecutorService;

/**
 * Initializes configurations for the application and module,
 * setting up event listeners and filters.
 */
public class InitializedConfiguration {

    private static final String NAME = "initializedConfiguration";

    /**
     * Configuration for initializing the module central.
     * Registers default event listeners for various events.
     */
    @Extension(NAME)
    public static class ApplicationInitializedConfiguration implements ApplicationConfiguration {
        @Override
        public void postInit(EffRpcApplication application) {
            // register default event listeners
            EventDispatcher eventDispatcher = application.eventDispatcher();
            eventDispatcher.registerListener(RefreshHeartBeatCountEvent.class, new RefreshHeartBeatCountEventListener());
            eventDispatcher.registerListener(IdleEvent.class, new IdleEventListener());
            eventDispatcher.registerListener(CallerMetricsEvent.class, new CallerMetricsEventListener());
            eventDispatcher.registerListener(CalleeMetricsEvent.class, new CalleeMetricsEventListener());
        }
    }

    /**
     * Configuration for initializing the module.
     * Registers shared filters for the module's caller and callee metrics.
     */
    @Extension(NAME)
    public static class ModuleInitializedConfiguration implements ModuleConfiguration {
        @Override
        public void postInit(EffiRpcModule module) {
            module.registerShared(new CalleeExecuteRecordFilter(), new CallerMetricsFilter(module));
            String serverHybrid = Constant.DEFAULT_SERVER_HYBRID_THREAD_POOL;
            ExecutorService serverHybridExecutor = RpcThreadPool.defaultIOExecutor(serverHybrid);
            module.register(new ThreadPool(serverHybrid, serverHybridExecutor));
            String clientHybrid = Constant.DEFAULT_CLIENT_HYBRID_THREAD_POOL;
            ExecutorService clientHybridExecutor = RpcThreadPool.defaultCPUExecutor(clientHybrid);
            module.register(new ThreadPool(serverHybrid, clientHybridExecutor));
        }
    }

}
